﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Windows.Foundation;

namespace NhWeather.Register;

public abstract class BaseRegister : INotifyPropertyChanged
{
    private byte? _deviceAddress;
    private string _deviceAddressHex = string.Empty;
    private ushort _regAddress;
    private string _regAddressHex = "0000";
    private short _data;
    private string _dataHex;
    private short? _maxValue;
    private short? _minValue;
    private int _changeAmplitude;

    /// <summary>
    /// 设备地址
    /// </summary>
    public byte? DeviceAddress
    {
        get => _deviceAddress;
        set
        {
            UpdateProperty(ref _deviceAddress, value, () =>
            {
                DeviceAddressHex = value?.ToString("X2") ?? string.Empty;
            });
        }
    }

    /// <summary>
    /// 16进制设备地址
    /// </summary>
    public string DeviceAddressHex
    {
        get => _deviceAddressHex;
        set
        {
            try
            {
                DeviceAddress = Convert.ToByte(value, 16);
                UpdateProperty(ref _deviceAddressHex, value);
            }
            catch { }
        }
    }

    /// <summary>
    /// 寄存器地址
    /// </summary>
    public ushort RegAddress
    {
        get => _regAddress;
        set
        {
            UpdateProperty(ref _regAddress, value, () =>
            {
                RegAddressHex = value.ToString("X4");
            });
        }
    }

    /// <summary>
    /// 16进制寄存器地址
    /// </summary>
    public string RegAddressHex
    {
        get => _regAddressHex;
        set
        {
            try
            {
                RegAddress = Convert.ToUInt16(value, 16);
                UpdateProperty(ref _regAddressHex, value);
            }
            catch { }
        }
    }

    protected List<byte> ControlCode { get; set; }


    /// <summary>
    /// 寄存器内的数据
    /// </summary>
    public short Data
    {
        get => _data;
        set => UpdateProperty(ref _data, value, () =>
            {
                DataHex = value.ToString("X4");
            });
    }


    /// <summary>
    /// 寄存器内的数据
    /// </summary>
    public string DataHex
    {
        get => _dataHex;
        set
        {
            try
            {
                Data = Convert.ToInt16(value, 16);
                UpdateProperty(ref _dataHex, value);
            }
            catch { }
        }
    }

    /// <summary>
    /// 最大值
    /// </summary>
    public short? MaxValue
    {
        get => _maxValue;
        set => UpdateProperty(ref _maxValue, value);
    }

    /// <summary>
    /// 最小值
    /// </summary>
    public short? MinValue
    {
        get => _minValue;
        set => UpdateProperty(ref _minValue, value);
    }

    /// <summary>
    /// 变化幅度
    /// </summary>
    public int ChangeAmplitude
    {
        get => _changeAmplitude;
        set => UpdateProperty(ref _changeAmplitude, value);
    }

    public BaseRegister()
    {
    }

    /// <summary>
    /// 属性改变事件句柄，双向绑定需要
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// 属性改变事件，双向绑定需要
    /// </summary>
    /// <param name="propertyName">已更改属性的名称，null参数指示所有属性已更改</param>
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    /// <summary>
    /// 更新属性并触发属性更改通知
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="properValue"></param>
    /// <param name="newValue"></param>
    /// <param name="onChanged">如要更改属性要运行的方法</param>
    /// <param name="propertyName"></param>
    protected void UpdateProperty<T>(ref T properValue, T newValue, Action onChanged = null, [CallerMemberName] string propertyName = null)
    {
        if (Equals(properValue, newValue))
        {
            return;
        }
        properValue = newValue;
        onChanged?.Invoke();
        OnPropertyChanged(propertyName);
    }

    /// <summary>
    /// 生成数据
    /// </summary>
    public abstract void Generate();
}
